const Field = require("./Field");

class Api {

    /**
     * Api 类的构造函数，用于初始化 Api 实例的属性。
     * 
     * @param {string} id - API 请求的唯一标识符，用于区分不同的 API 请求。
     * @param {URL} url - API 请求的目标 URL，指定请求发送的地址。
     * @param {string} method - API 请求使用的 HTTP 方法，如 'GET'、'POST' 等。
     * @param {{name: string, value: string}[]} headers - API 请求中包含的头部信息，用于传递额外的元数据。
     * @param {any} request - API 请求的数据，可以是对象、数组、基本类型等。
     * @param {any} response - API 响应的数据，可以是对象、数组、基本类型等。
     * @param {number} startTime - API 请求开始的时间，用于记录请求的起始时间。
     * @param {number} endTime - API 请求结束的时间，用于记录请求的结束时间。
     */
    constructor(id, url, method, headers, request, response, startTime, endTime) {
        this.id = id;
        this.url = url;
        this.method = method;
        this.headers = headers;
        this.request = request;
        this.response = response;
        this.startTime = startTime;
        this.endTime = endTime;
        /** @type {Field[]} */
        this.requestFields = this._getFields(request);
        /** @type {Field[]} */
        this.responseFields = this._getFields(response);
    }

    _getFields(obj, prefix = '$', result = []) {
        if (typeof obj !== 'object' || obj === null) {
            const name = Api._getFieldNameByJsonPath(prefix);
            const value = Api._isJSONString(obj) ? JSON.parse(obj) : obj;
            const jsonPath = prefix;
            result.push(new Field(this.url.pathname, name, value, jsonPath));
            return result;
        }

        if (Array.isArray(obj)) {
            for (let i = 0; i < obj.length; i++) {
                const currentPath = `${prefix}[${i}]`;
                this._getFields(obj[i], currentPath, result);
            }
        } else {
            for (const [key, value] of Object.entries(obj)) {
                const currentPath = `${prefix}.${key}`;
                this._getFields(value, currentPath, result);
            }
        }

        return result;
    }

    static _getFieldNameByJsonPath(jsonPath) {
        const pathWithoutBrackets = jsonPath.replace(/\[[^\]]*\]/g, '');
        const match = pathWithoutBrackets.match(/[^.\[\]]+$/)
        return match ? match[0] : null;
    }

    static _isJSONString(str) {
        try {
            const parsed = JSON.parse(str);
            return typeof parsed === 'object' && (Array.isArray(parsed) || !Array.isArray(parsed));
        } catch (error) {
            return false;
        }
    }
}

module.exports = Api;